package com.easyedu.dean.service.arrange;

import com.easyedu.core.entity.dto.DepartmentYear;
import com.easyedu.core.entity.po.Classroom;
import com.easyedu.core.entity.po.OpenCourse;
import com.easyedu.core.entity.po.OpenCourseTime;
import com.easyedu.core.dao.OpenCourseTimeMidDao;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
 * @author mengranliu
 * @date 2022/3/12
 */
@Service
public class DepartmentPackageService {


     @Autowired
     private OpenCourseTimeMidDao openCourseTimeMidDao;

     /**
      * 专业id
      */
     private long departmentId;

     /**
      * 专业名称
      */
     private String departmentName;

     /**
      * 年级
      */
     private int grade;

     /**
      * 学生人数
      */
     private long studentNumber;

     private boolean isFirst = true;

     private String versionId = "";

     private CoursePackage nextPackage = new CoursePackage();


     /**
      * 课程座位和课程列表list
      */
     private Map<Long, List<OpenCourse>> openCourseMap = new HashMap<>();
     /**
      * 已经排课的课程
      */
     private List<OpenCourse> hasArrangeCourse = new ArrayList<>();
     /**
      * 没有排课的课程
      */
     private List<OpenCourse> notArrangeCourse = new ArrayList<>();
     /**
      * 无法排课的课程
      */
     private List<OpenCourse> cannotArrangeCourse = new ArrayList<>();

     private long[] seatLevel;


     public List<OpenCourse> getCannotArrangeCourse() {

          return cannotArrangeCourse;
     }

     public class CoursePackage {

          /**
           * 此课程包所需教室大小
           */
          private int seat;

          /**
           * 一个包中的4个，1为1节，2为2节
           */
          private long[] openCourseIdArray = new long[2];

          public long[] getOpenCourseIdArray() {

               return openCourseIdArray;
          }

          public void putCourseToPackage(OpenCourse openCourse, OpenCourse sameCourseCodeCourse, int i, int j) {

               openCourseIdArray[i] = openCourse.getOpenCoursesId();
               openCourseIdArray[j] = sameCourseCodeCourse.getOpenCoursesId();

          }

          public boolean hasEmpty() {

               for (long l : openCourseIdArray) {
                    if (l == 0) {
                         return true;
                    }
               }
               return false;
          }

          public void putCourseToPackage(OpenCourse openCourse, int j) {

               openCourseIdArray[j] = openCourse.getOpenCoursesId();

          }
     }


     public void init(DepartmentYear departmentYear, List<OpenCourse> notArrangeCourse,
                      OpenCourseTimeMidDao openCourseTimeMidDao,String versionId) {

          this.openCourseTimeMidDao = openCourseTimeMidDao;
          this.departmentId = departmentYear.getDepartmentId();
          this.departmentName = departmentYear.getDepartmentName();
          this.grade = departmentYear.getGrade();
          this.studentNumber = departmentYear.getStudentNumber();
          //构建seat等级
          this.notArrangeCourse = notArrangeCourse;
          for (OpenCourse openCourse : notArrangeCourse) {
               long capacity = openCourse.getCapacity();
               List<OpenCourse> orDefault = openCourseMap.getOrDefault(capacity, new ArrayList<>());
               orDefault.add(openCourse);
               openCourseMap.put(capacity, orDefault);

          }
          Set<Long> seatLevel = openCourseMap.keySet();
          int setSize = seatLevel.size();
          this.seatLevel = new long[setSize];
          int i = 0;
          for (Long aLong : seatLevel) {
               this.seatLevel[i] = aLong;
               i++;
          }
          Arrays.sort(this.seatLevel);
          this.versionId = versionId;
     }

     public CoursePackage getNextPackage(Classroom classroom, int packageNumber) {

          if (notArrangeCourse.size() == 0) {
               //无可排课程
               return null;
          }
          if (classroom.getSeats() < seatLevel[0]) {
               //教室太小
               return null;
          }
          CoursePackage coursePackage = new CoursePackage();
          for (int i = seatLevel.length - 1; i >= 0; i--) {
               if (!coursePackage.hasEmpty()) {
                    break;
               }
               if (seatLevel[i] <= classroom.getSeats()) {
                    //可以排课
//                    if (this.isFirst) {
//                         this.isFirst = false;
//                    }

                    //找出对应的课程
                    List<OpenCourse> openCourses = openCourseMap.get(seatLevel[i]);
                    if (openCourses == null || openCourses.isEmpty()){
                         continue;
                    }
                    for (OpenCourse openCourse : openCourses) {
                         if (!coursePackage.hasEmpty()) {
                              break;
                         }
                         if (coursePackage.getOpenCourseIdArray()[0] == 0) {
                              if (!courseAtPackageHasConflict(openCourse, 0, packageNumber)) {
                                   //可以排课
                                   coursePackage.putCourseToPackage(openCourse, 0);
                                   notArrangeCourse.remove(openCourse);
                                   hasArrangeCourse.add(openCourse);
                                   continue;
                              }
                         }
                         if (coursePackage.getOpenCourseIdArray()[1] == 0) {
                              if (!courseAtPackageHasConflict(openCourse, 1, packageNumber)) {
                                   //可以排课
                                   coursePackage.putCourseToPackage(openCourse, 1);
                                   notArrangeCourse.remove(openCourse);
                                   hasArrangeCourse.add(openCourse);
                                   continue;
                              }
                         }
//                         OpenCourse sameCourseCodeCourse = getSameCourseCodeCourse(openCourse);
//                         if (sameCourseCodeCourse != null) {
//                              //TODO 如果老师相同，就放在 不同时间，如果老师不同，放相同时间
//                              if (!courseAtPackageHasConflict(openCourse, sameCourseCodeCourse, 1, 2,
//                              packageNumber)) {
//                                   coursePackage.putCourseToPackage(openCourse, sameCourseCodeCourse, 1, 2);
//                              } else if (!courseAtPackageHasConflict(openCourse, sameCourseCodeCourse, 3, 4,
//                                      packageNumber)) {
//                                   coursePackage.putCourseToPackage(openCourse, sameCourseCodeCourse, 3, 4);
//                              } else if (!courseAtPackageHasConflict(openCourse, sameCourseCodeCourse, 1, 3,
//                                      packageNumber)) {
//                                   coursePackage.putCourseToPackage(openCourse, sameCourseCodeCourse, 1, 3);
//                              } else if (!courseAtPackageHasConflict(openCourse, sameCourseCodeCourse, 3, 1,
//                                      packageNumber)) {
//                                   coursePackage.putCourseToPackage(openCourse, sameCourseCodeCourse, 3, 1);
//                              } else if (!courseAtPackageHasConflict(openCourse, sameCourseCodeCourse, 2, 4,
//                                      packageNumber)) {
//                                   coursePackage.putCourseToPackage(openCourse, sameCourseCodeCourse, 2, 4);
//                              } else if (!courseAtPackageHasConflict(openCourse, sameCourseCodeCourse, 4, 2,
//                                      packageNumber)) {
//                                   coursePackage.putCourseToPackage(openCourse, sameCourseCodeCourse, 4, 2);
//                              } else {
//                                   //这两个课程没有可以排的时间
//                                   notArrangeCourse.remove(openCourse);
//                                   notArrangeCourse.remove(sameCourseCodeCourse);
//                                   cannotArrangeCourse.add(openCourse);
//                                   cannotArrangeCourse.add(sameCourseCodeCourse);
//                                   continue;
//                              }
//                              //可以排
//                              notArrangeCourse.remove(openCourse);
//                              notArrangeCourse.remove(sameCourseCodeCourse);
//                              hasArrangeCourse.add(openCourse);
//                              hasArrangeCourse.add(sameCourseCodeCourse);
//                              resetOpenCourseMap();
//                              break;
//                         } else {
//                              boolean arrangeSuccess = false;
//                              for (int j = 1; j <= 2; j++) {
//                                   if (!courseAtPackageHasConflict(openCourse, j, packageNumber)) {
//                                        //可以排课
//                                        coursePackage.putCourseToPackage(openCourse, j);
//                                        notArrangeCourse.remove(openCourse);
//                                        hasArrangeCourse.add(openCourse);
//                                        arrangeSuccess = true;
//                                   }
//                              }
//                              if (!arrangeSuccess) {
//                                   //无法排课
//                                   notArrangeCourse.remove(openCourse);
//                                   cannotArrangeCourse.add(openCourse);
//                              }
//                         }
                    }
               }
          }
          resetOpenCourseMap();
          return coursePackage;
     }

     private void resetOpenCourseMap() {

          openCourseMap = new HashMap<>();
          for (OpenCourse openCourse : notArrangeCourse) {
               long capacity = openCourse.getCapacity();
               List<OpenCourse> orDefault = openCourseMap.getOrDefault(capacity, new ArrayList<>());
               orDefault.add(openCourse);
               openCourseMap.put(capacity, orDefault);
          }

     }

     private boolean courseAtPackageHasConflict(OpenCourse openCourse, OpenCourse sameCourseCodeCourse, int i, int j,
             int packageNumber) {

          if (!courseAtPackageHasConflict(openCourse, i, packageNumber) && !courseAtPackageHasConflict(
                  sameCourseCodeCourse, j, packageNumber)) {
               //这两个课程也不冲突
               if (i + j == 3 || i + j == 7) {
                    if (openCourse.getTeacherId() != sameCourseCodeCourse.getTeacherId()) {
                         return false;
                    }
               }
          }
          return true;
     }

     /**
      * 是否存在冲突课程
      *
      * @param openCourse
      * @param i
      * @param packageNumber
      * @return
      */
     private boolean courseAtPackageHasConflict(OpenCourse openCourse, int i, int packageNumber) {
          //老师没冲突
          long teacherId = openCourse.getTeacherId();
          long openYear = openCourse.getOpenYear();
          String semester = openCourse.getSemester();
          List<OpenCourseTime> teacherCourse = openCourseTimeMidDao.getTeacherCourse(teacherId, openYear, semester,versionId);
          if (teacherCourse == null || teacherCourse.isEmpty()) {
               return false;
          } else {
               for (OpenCourseTime openCourseTime : teacherCourse) {
                    int openDay = openCourseTime.getOpenDay();
                    int openLesson = openCourseTime.getOpenLesson();
                    if (openDay == (packageNumber / 2 + 1)) {
                         int classLesson;
                         if (packageNumber == 0 || packageNumber == 2 || packageNumber == 4) {
                              classLesson = i + 1;
                         } else {
                              if (i == 0) {
                                   classLesson = 3;
                              } else {
                                   classLesson = 4;
                              }
                         }
                         if (classLesson == openLesson) {
                              return true;
                         }
                    }
               }
          }
          return false;
     }

     /**
      * 找到具有相同课号的课程
      *
      * @param openCourse
      * @return
      */
     private OpenCourse getSameCourseCodeCourse(OpenCourse openCourse) {

          for (OpenCourse course : notArrangeCourse) {
               if (course.getCourseCode().equals(openCourse.getCourseCode())) {
                    return course;
               }
          }
          return null;
     }
}
